public class SharedData {
	private int here; // modified by LiftHandler only
	private int next; // modified by LiftHandler only
	private int load; // modified by PersonHandler only
	private int[] waitEntry; // modified by PersonHandler only
	private int[] waitExit; // modified by PersonHandler only
	private LiftView lv;
	private boolean moveUp;

	public SharedData(LiftView lv) {
		waitEntry=new int[7];
		waitExit=new int[7];		
		this.lv = lv;
	}

	public synchronized void callElevator(int initial, int target) {
		updateLevel(initial);

		enterElevator(initial, target);

		leaveElevator(target);
	}

	public void moveLift() {
		int a=0;
		int b=0;
		synchronized (this) {
			while ((waitExit[here] > 0) || (waitEntry[here] != 0 && load < 4)
					|| (load == 0 && entryIsEmtpy())) {
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			a=here;
			b = getNextFloor();			
		}
		
		lv.moveLift(a, b);

		synchronized (this) {
			here = next;
			notifyAll();
		}
	}

	private int getNextFloor() {
		if (here == 6) {
			moveUp = false;
			return --next;
		} else if (here == 0) {
			moveUp = true;
			return ++next;
		}

		return moveUp? ++next : --next;
	}

	private boolean entryIsEmtpy() {
		for (int i = 0; i < waitEntry.length; i++) {
			if (waitEntry[i] != 0) {
				return false;
			}
		}
		return true;
	}

	private void updateLevel(int initial) {
		waitEntry[initial]++;
		drawLevel(initial);
		notifyAll();
	}

	private void enterElevator(int initial, int target) {
		while (load == 4 || here != initial || here!=next) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		waitExit[target]++;
		load++;
		drawLift(here);
		waitEntry[initial]--;
		drawLevel(here);
		notifyAll();
	}

	private void leaveElevator(int target) {
		while (here != target) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		waitExit[here]--;
		load--;
		drawLift(here);
		notifyAll();
	}

	private void drawLevel(int initial) {
		lv.drawLevel(initial, waitEntry[initial]);
	}

	private void drawLift(int here) {
		lv.drawLift(here, load);
	}

	// public synchronized void updateEntry(int initial) {
	// waitEntry[initial]++;
	// lv.drawLevel(here, waitEntry[here]);
	// notifyAll();
	// }
	//
	//	
	// public synchronized void updateExit(int target) {
	// while (here != next) {
	// try {
	// wait();
	// } catch (InterruptedException e) {
	// e.printStackTrace();
	// }
	// }
	//
	// if (load < 4) {
	// waitExit[target]++;
	// waitEntry[initial]--;
	// load++;
	// lv.drawLift(here, load);
	// notifyAll();
	// }
	//
	// }
	//	
	// public synchronized void decreaseWaitEntry() {
	//		
	// }
	//	
	// public synchronized void decreaseWaitExit() {
	//		
	// }
}
